#ifndef __RED_C_FUNCTION_OBJECT_H__
#define __RED_C_FUNCTION_OBJECT_H__

#include "redobject.h"

typedef enum _RedCFunctionType
{
	cf_vfunc,
	cf_vmethod,

	cf_unary,
	cf_binary,
	cf_ternary,
	cf_nullary,
} RedCFunctionType;

typedef RedObject *(* RedCUnaryFunction)(RedObject *self);
typedef RedObject *(* RedCBinaryFunction)(RedObject *self, RedObject *args);
typedef RedObject *(* RedCTernaryFunction)(RedObject *self, RedObject *other, RedObject *args);
typedef RedObject *(* RedCNullaryFunction)(void);

typedef struct _RedCFunctionObject
{
	RedObject_HEAD

	RedCFunctionType			cf_type;

	union
	{
		RedCUnaryFunction		cf_unary;
		RedCBinaryFunction		cf_binary;
		RedCTernaryFunction		cf_ternary;
		RedCNullaryFunction		cf_nullary;
	};
} RedCFunctionObject;

RED_EXPORT extern RedTypeObject RedType_CFunction;

#define RedCFunction_Exact(o)		((o)->ob_type == &RedType_CFunction)

#define RedCFunction_Type(o)		(((RedCFunctionObject *)(o))->cf_type)
#define RedCFunction_Unary(o)		(((RedCFunctionObject *)(o))->cf_unary)
#define RedCFunction_Binary(o)		(((RedCFunctionObject *)(o))->cf_binary)
#define RedCFunction_Ternary(o)		(((RedCFunctionObject *)(o))->cf_ternary)
#define RedCFunction_Nullary(o)		(((RedCFunctionObject *)(o))->cf_nullary)

RED_EXPORT RedObject *RedCFunction_WrapVarFunc(RedCUnaryFunction func);
RED_EXPORT RedObject *RedCFunction_WrapVarMethod(RedCBinaryFunction method);

RED_EXPORT RedObject *RedCFunction_WrapUnary(RedCUnaryFunction unary);
RED_EXPORT RedObject *RedCFunction_WrapBinary(RedCBinaryFunction binary);
RED_EXPORT RedObject *RedCFunction_WrapTernary(RedCTernaryFunction ternary);
RED_EXPORT RedObject *RedCFunction_WrapNullary(RedCNullaryFunction nullary);

RED_EXPORT RedObject *RedCFunction_Invoke(RedObject *self, RedObject *args);

#endif /* __RED_C_FUNCTION_OBJECT_H__ */
